﻿//////////////////////////////////////////////////////////////////////
// Copyright© 2021 
// Author: hchlqlz
// DateTime: 2021-08-17
// Describe: 日志功能相关
//////////////////////////////////////////////////////////////////////
#pragma once

#include <string>
#include <format>
using std::string;

#include "stacktrace.h"

#define CHECK(x) do { if( !(x) ) { XLog::LogError("★CHECK({})★ in {}, {}", #x, __FILE__, __LINE__); return ; } } while(0)
#define CHECKF(x) do { if( !(x) ) { XLog::LogError("★CHECKF({})★ in {}, {}", #x, __FILE__, __LINE__); return 0; } } while(0)
#define CHECK_2(x, n, level) do { if( !(x) ) { XLog::LogError("★CHECK_2({}), {}={}★ in {}, {} {}", #x, #n, n, __FILE__, __LINE__, XLog::GetStackTrace(level)); return ; } } while(0)
#define CHECKF_2(x, n, level) do { if( !(x) ) { XLog::LogError("★CHECK_2({}), {}={}★ in {}, {} {}", #x, #n, n, __FILE__, __LINE__, XLog::GetStackTrace(level)); return 0; } } while(0)

#define IF_OK(x) if( (x) ? 1 : (XLog::LogError("★IF_OK({})★ in {}, {}", #x, __FILE__, __LINE__), 0))
#define IF_NOT(x) if( !(x) ? (XLog::LogError("★IF_NOT({})★ in {}, {}", #x, __FILE__, __LINE__), 1) : 0)
#define IF_OK_2(x, n, level) if( (x) ? 1 : (XLog::LogError("★IF_OK_2({}), {}={}★ in {}, {} {}", #x, #n, n, __FILE__, __LINE__, XLog::GetStackTrace(level)), 0))
#define IF_NOT_2(x, n, level) if( !(x) ? (XLog::LogError("★IF_NOT_2({}), {}={}★ in {}, {} {}", #x, #n, n, __FILE__, __LINE__, XLog::GetStackTrace(level)), 1) : 0 )

#define SAFE_DELETE(ptr) { if(ptr){ try{ delete ptr; }catch(...){ XLog::LogError("★DELETE★ in {}, {}", __FILE__, __LINE__); } ptr = 0;  } }
#define SAFE_RELEASE(ptr) { if(ptr){ try{ ptr->Release(); }catch(...){ XLog::LogError("★RELEASE★ in {}, {}", __FILE__, __LINE__); } ptr = 0; } }

#define SAFE_DELETE_ARRAY(ptr) { if(ptr){ try{ delete[] ptr; }catch(...){ XLog::LogError("★DELETE[]★ in {}, {}", __FILE__, __LINE__); } ptr = 0;  } }

#define DEAD_LOOP_BREAK(x, n) { if (++(x) > (n)) { XLog::LogError("★DEAD_LOOP_BREAK★ in {}, {}", __FILE__, __LINE__); break; } }

#ifndef _DEBUG 
#define DEBUG_TRY try{
#define DEBUG_CATCH0 DEBUG_CATCH("")
#define DEBUG_CATCH(s) } catch(std::exception e) { XLog::LogError("CATCH: ({}){} in {} at {}, {}", s, e.what(), __FUNCTION__, __FILE__, __LINE__); } catch(...) { XLog::LogError("CATCH: ({})... in {} at {}, {}", (s), __FUNCTION__, __FILE__, __LINE__); }
#else
#define DEBUG_TRY {
#define DEBUG_CATCH0 }
#define DEBUG_CATCH(s) }
#endif

#define LOGKEY_SYSTEM		"system"
#define FILENAME_SYSTEM		"syslog/{}_%Y_%m_%d.log"

#ifdef _DEBUG
#define DEBUG_MSG(x, ...) XLog::PrintToConsole(x, __VA_ARGS__)
#else
#define DEBUG_MSG(x, ...) 
#endif

namespace XLog
{
	void Initialize(string projectName);

	void LogError(const std::string& msg);

	template <class... _Types>
	void LogError(const std::string_view _Fmt, const _Types&... _Args)
	{
		LogError(std::vformat(_Fmt, std::make_format_args(_Args...)));
	}

	void LogMsg(const std::string& msg);

	template <class... _Types>
	void LogMsg(const std::string_view _Fmt, const _Types&... _Args)
	{
		LogMsg(std::vformat(_Fmt, std::make_format_args(_Args...)));
	}

	void PrintToConsole(const std::string& msg);

	template <class... _Types>
	void PrintToConsole(const std::string_view _Fmt, const _Types&... _Args)
	{
		PrintToConsole(std::vformat(_Fmt, std::make_format_args(_Args...)));
	}

	void FileFlush();
}